package com.sunday.common.leaf.core;

import com.sunday.common.core.utils.CompressEncoding62Utils;
import com.sunday.common.leaf.Result;
import com.sunday.common.leaf.config.LeafProperties;
import com.sunday.common.leaf.enums.Status;
import com.sunday.common.leaf.snowflake.SnowflakeIDGenImpl;
import com.sunday.common.leaf.snowflake.SnowflakeZookeeperMonitor;
import com.sunday.common.leaf.snowflake.constants.SnowflakeConstants;
import lombok.extern.slf4j.Slf4j;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ThreadLocalRandom;

@Slf4j
public class IdWorker {

    private static SnowflakeIDGenImpl snowflakeID;

    private static SnowflakeZookeeperMonitor monitor;

    public static void build(LeafProperties leafProperties) {
        log.info("[Snowflake] leaf properties : {}", leafProperties);
        assert leafProperties != null : "leafProperties must not be null";
        assert leafProperties.getName() != null || !leafProperties.getName().contains("_") : "leaf name illegal format";
        assert leafProperties.getPort() != null : "leaf port must not be null";
        assert leafProperties.getZkAddress() != null : "leaf zkAddress must not be null";
        /**  初始化雪花算法  */
        SnowflakeConstants.init(leafProperties);
        /**  分布式ID实现  */
        snowflakeID = SnowflakeIDGenImpl.of(leafProperties.getZkAddress(), leafProperties.getPort());
        /**  分布式ID监听器  */
        if (leafProperties.isOpenMonitor()) {
            monitor = SnowflakeZookeeperMonitor.of(leafProperties.getZkAddress(), leafProperties.getPort());
        }
    }

    /**
     * 获取工作节点ID
     *
     * @return {@link long}
     */
    public static long getWorkerId() {
        return snowflakeID.getWorkerId();
    }

    /**
     * 获取分布式ID
     *
     * @return {@link long}
     */
    public static long getId() {
        Result result = snowflakeID.get();
        //解析状态码
        if (Status.SUCCESS.equals(result.status())) {
            return result.id();
        } else {
            /**
             * -3 超过时钟最大等待范围
             * -2 等待中断
             * -1 时钟回拨失败
             */
            throw new RuntimeException("Get ID exception, error code ： " + result.id());
        }
    }

    /**
     * long 62进制
     *
     * @return {@link String}
     */
    public static String get62Id() {
        return CompressEncoding62Utils.compressNumber(getId());
    }

    /**
     * 解析分布式ID生成的时间戳
     *
     * @param id
     * @return {@link LocalDateTime}
     */
    public static LocalDateTime parseId(long id) {
        return LocalDateTime.ofInstant(
                Instant.ofEpochMilli(snowflakeID.getTimestamp(id)),
                ZoneId.systemDefault());
    }

    /**
     * 解析62进制分布式ID生成的时间戳
     *
     * @param id
     * @return {@link LocalDateTime}
     */
    public static LocalDateTime parse62Id(String id) {
        return parseId(CompressEncoding62Utils.unCompressNumber(id));
    }

    /**
     * 使用ThreadLocalRandom获取UUID获取更优的效果 去掉"-"
     *
     * @param
     * @return {@link String}
     */
    public static String get32UUID() {
        ThreadLocalRandom random = ThreadLocalRandom.current();
        return new UUID(random.nextLong(), random.nextLong()).toString().replace("-", "");
    }

    /**
     * 检索当前名称和当前端口所有节点的存活状态
     *
     * @return {@link Set< Integer>}
     */
    public static Set<Integer> getAliveNode() {
        assert monitor != null : "monitor must not be null";
        return monitor.getAliveNode();
    }

    /**
     * 检索当前名称和指定的端口的节点存活状态
     *
     * @param port
     * @return {@link Set< Integer>}
     */
    public static Set<Integer> getAliveNode(int port) {
        assert monitor != null : "monitor must not be null";
        return monitor.getAliveNode(port);
    }

}